
package com.trydofor.id.exec;

import java.util.List;
import java.util.Map;

import com.trydofor.aloe.exception.Exceptions;
import com.trydofor.id.body.int64.Int64QueryBody;
import com.trydofor.id.body.int64.Int64ReplyBody;
import com.trydofor.id.byta.Head;
import com.trydofor.id.byta.Packet;
import com.trydofor.id.core.A9Maker;
import com.trydofor.id.doer.int64.Int64Doer;
import com.trydofor.id.doer.shell.ArgChecker;
import com.trydofor.id.doer.shell.Command;
import com.trydofor.id.doer.shell.Executer;
import com.trydofor.id.doer.shell.Outcome;
import com.trydofor.id.ware.WareFactory;

/**
 * @author : Shi Rongjiu (www.trydofor.com)
 */
public class Int64Exe implements Executer {
    
    private final Command     registerMaker;
    private final Command     unregisterMaker;
    private final Command     query;
    private final Command     listMaker;
    
    private final Int64Doer   int64Doer;
    private final WareFactory factory;
    
    /**
     * constructor
     * 
     * @param doer the shell
     * @param factory the ware context
     * @throws NullPointerException if doer or factory is null
     */
    public Int64Exe(Int64Doer doer, WareFactory factory) {
        Exceptions.checkNullPointer(doer);
        Exceptions.checkNullPointer(factory);
        this.int64Doer = doer;
        this.factory = factory;
        this.registerMaker = Int64Cmd.registerMaker();
        this.unregisterMaker = Int64Cmd.unregisterMaker();
        this.query = Int64Cmd.query();
        this.listMaker = Int64Cmd.listMaker();
    }
    
    /**
     * {@inheritDoc}
     */
    public Outcome execute(Command command, Map<String, String> argdata) {
        
        String err = ArgChecker.check(command, argdata);
        if (err != null) return new Outcome(-1, null, err);
        
        if (registerMaker.getAlias().equals(command.getAlias())) {
            return register(command, argdata);
        }
        else if (unregisterMaker.getAlias().equals(command.getAlias())) {
            return unregister(command, argdata);
        }
        else if (query.getAlias().equals(command.getAlias())) {
            return query(command, argdata);
        }
        else if (listMaker.getAlias().equals(command.getAlias())) {
            return listMaker(command, argdata);
        }
        return new Outcome(-1, null, "Command is unsupported:" + command);
    }
    
    // ------------------
    private Outcome register(Command command, Map<String, String> argdata) {
        try {
            String tyn = argdata.get("name");
            String mkn = argdata.get("maker");
            @SuppressWarnings("unchecked")
            A9Maker<? extends Number> mk = (A9Maker<? extends Number>) factory.getInstance(mkn);
            if (mk == null) {
                return new Outcome(-2, "A9Maker Not Found:" + mkn, null);
            }
            
            int64Doer.register(tyn, mk);
            return new Outcome(0, "register the a9maker:" + mkn, null);
        }
        catch (Exception e) {
            return new Outcome(-1, null, Exceptions.printStackTrace(e));
        }
        
    }
    
    private Outcome unregister(Command command, Map<String, String> argdata) {
        try {
            String mkn = argdata.get("name");
            int64Doer.unregister(mkn);
            return new Outcome(0, "unregister the a9maker:"+mkn, null);
        }
        catch (Exception e) {
            return new Outcome(-1, null, Exceptions.printStackTrace(e));
        }
    }
    
    private Outcome query(Command command, Map<String, String> argdata) {
        try {
            String mkn = argdata.get("maker");
            String lmt = argdata.get("count");
            String acd = argdata.get("authcode");
            Int64QueryBody b = new Int64QueryBody(mkn, Integer.parseInt(lmt));
            Packet p = new Packet(new Head(Integer.parseInt(acd), System.nanoTime()), b);
            Packet r = int64Doer.response(p);
            Int64ReplyBody br = (Int64ReplyBody) r.getBody();
            StringBuilder sb = new StringBuilder();
            for (long n : br.getLongs()) {
                sb.append(n).append('\n');
            }
            return new Outcome(0, sb.toString(), null);
        }
        catch (Exception e) {
            return new Outcome(-1, null, Exceptions.printStackTrace(e));
        }
    }
    
    private Outcome listMaker(Command command, Map<String, String> argdata) {
        try {
            List<String> r = int64Doer.listMaker();
            StringBuilder sb = new StringBuilder();
            for (String n : r) {
                sb.append(n).append('\n');
            }
            return new Outcome(0, sb.toString(), null);
        }
        catch (Exception e) {
            return new Outcome(-1, null, Exceptions.printStackTrace(e));
        }
    }
}
